{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Magnetostatic Fields\n",
    "================="
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[magnetostatics]: https://docs.plasmapy.org/en/stable/formulary/magnetostatics.html\n",
    "[plasmapy.formulary]: https://docs.plasmapy.org/en/stable/formulary/\n",
    "\n",
    "This notebook presents examples of using PlasmaPy's [magnetostatics] module in [plasmapy.formulary]."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "\n",
    "import astropy.units as u\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "from plasmapy.formulary import magnetostatics\n",
    "from plasmapy.plasma.sources import Plasma3D\n",
    "\n",
    "plt.rcParams[\"figure.figsize\"] = [10.5, 10.5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Common magnetostatic fields, like those from a magnetic dipole, can be generated and added to a plasma object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "dipole = magnetostatics.MagneticDipole(\n",
    "    np.array([0, 0, 1]) * u.A * u.m * u.m, np.array([0, 0, 0]) * u.m\n",
    ")\n",
    "print(dipole)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, we will initialize a plasma on which the magnetic field will be calculated."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "plasma = Plasma3D(\n",
    "    domain_x=np.linspace(-2, 2, 30) * u.m,\n",
    "    domain_y=np.linspace(0, 0, 1) * u.m,\n",
    "    domain_z=np.linspace(-2, 2, 20) * u.m,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's then add the dipole field to it, and plot the results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "plasma.add_magnetostatic(dipole)\n",
    "\n",
    "X, Z = plasma.grid[0, :, 0, :], plasma.grid[2, :, 0, :]\n",
    "U = plasma.magnetic_field[0, :, 0, :].value.T  # because grid uses 'ij' indexing\n",
    "W = plasma.magnetic_field[2, :, 0, :].value.T  # because grid uses 'ij' indexing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": [
     "nbsphinx-thumbnail"
    ]
   },
   "outputs": [],
   "source": [
    "plt.figure()\n",
    "plt.axis(\"square\")\n",
    "plt.xlim(-2, 2)\n",
    "plt.ylim(-2, 2)\n",
    "plt.xlabel(\"x\")\n",
    "plt.ylabel(\"z\")\n",
    "plt.title(\"Dipole magnetic field\")\n",
    "plt.streamplot(plasma.x.value, plasma.z.value, U, W)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "raw_mimetype": "text/restructuredtext"
   },
   "source": [
    "[CircularWire]: https://docs.plasmapy.org/en/stable/api/plasmapy.formulary.magnetostatics.CircularWire.html#plasmapy.formulary.magnetostatics.CircularWire\n",
    "\n",
    "Next let's calculate the magnetic field from a current-carrying loop with [CircularWire]."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "cw = magnetostatics.CircularWire(\n",
    "    np.array([0, 0, 1]), np.array([0, 0, 0]) * u.m, 1 * u.m, 1 * u.A\n",
    ")\n",
    "print(cw)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's initialize another plasma object, add the magnetic field from the circular wire to it, and plot the result."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "plasma = Plasma3D(\n",
    "    domain_x=np.linspace(-2, 2, 30) * u.m,\n",
    "    domain_y=np.linspace(0, 0, 1) * u.m,\n",
    "    domain_z=np.linspace(-2, 2, 20) * u.m,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "plasma.add_magnetostatic(cw)\n",
    "\n",
    "X, Z = plasma.grid[0, :, 0, :], plasma.grid[2, :, 0, :]\n",
    "U = plasma.magnetic_field[0, :, 0, :].value.T  # because grid uses 'ij' indexing\n",
    "W = plasma.magnetic_field[2, :, 0, :].value.T  # because grid uses 'ij' indexing\n",
    "\n",
    "plt.figure()\n",
    "plt.axis(\"square\")\n",
    "plt.xlim(-2, 2)\n",
    "plt.ylim(-2, 2)\n",
    "plt.xlabel(\"x\")\n",
    "plt.ylabel(\"z\")\n",
    "plt.title(\"Magnetic field from a circular coil\")\n",
    "plt.tight_layout()\n",
    "plt.streamplot(plasma.x.value, plasma.z.value, U, W)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "raw_mimetype": "text/restructuredtext"
   },
   "source": [
    "[GeneralWire]: https://docs.plasmapy.org/en/stable/api/plasmapy.formulary.magnetostatics.GeneralWire.html#plasmapy.formulary.magnetostatics.GeneralWire\n",
    "\n",
    "A circular wire can be described as parametric equation and converted to a [GeneralWire].  Let's do that, and check that the resulting magnetic fields are close."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "gw_cw = cw.to_GeneralWire()\n",
    "\n",
    "print(gw_cw.magnetic_field([0, 0, 0]) - cw.magnetic_field([0, 0, 0]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "raw_mimetype": "text/restructuredtext"
   },
   "source": [
    "[InfiniteStraightWire]: https://docs.plasmapy.org/en/stable/api/plasmapy.formulary.magnetostatics.InfiniteStraightWire.html#plasmapy.formulary.magnetostatics.InfiniteStraightWire\n",
    "\n",
    "Finally, let's use [InfiniteStraightWire] to calculate the magnetic field from an infinite straight wire, add it to a plasma object, and plot the results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "iw = magnetostatics.InfiniteStraightWire(\n",
    "    np.array([0, 1, 0]), np.array([0, 0, 0]) * u.m, 1 * u.A\n",
    ")\n",
    "print(iw)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "plasma = Plasma3D(\n",
    "    domain_x=np.linspace(-2, 2, 30) * u.m,\n",
    "    domain_y=np.linspace(0, 0, 1) * u.m,\n",
    "    domain_z=np.linspace(-2, 2, 20) * u.m,\n",
    ")\n",
    "\n",
    "plasma.add_magnetostatic(iw)\n",
    "\n",
    "X, Z = plasma.grid[0, :, 0, :], plasma.grid[2, :, 0, :]\n",
    "U = plasma.magnetic_field[0, :, 0, :].value.T  # because grid uses 'ij' indexing\n",
    "W = plasma.magnetic_field[2, :, 0, :].value.T  # because grid uses 'ij' indexing\n",
    "\n",
    "plt.figure()\n",
    "plt.title(\"Magnetic field from an infinite straight wire\")\n",
    "plt.axis(\"square\")\n",
    "plt.xlim(-2, 2)\n",
    "plt.ylim(-2, 2)\n",
    "plt.xlabel(\"x\")\n",
    "plt.ylabel(\"z\")\n",
    "plt.tight_layout()\n",
    "plt.streamplot(plasma.x.value, plasma.z.value, U, W)\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3"
  },
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "state": {},
    "version_major": 2,
    "version_minor": 0
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
